package app;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.Vector;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.xml.sax.SAXException;
import exceptions.ProductoException;
import srv.*;
import xmlParsers.SystemParserBuscador;
import xmlParsers.SystemParserLeerRemito;

import xmlParsers.XmlBuildOrdenCompra;
import xmlParsers.XmlBuildRemito;
import beans.ProductoVO;
import negocio.Deposito;
import negocio.ItemRemito;
import negocio.Item_Compra;
import negocio.OrdenCompra;
import negocio.PlanProduccion;
import negocio.Producto;
import negocio.ProductosAComprar;
import negocio.Remito;

import negocio.SolicitudReposicion;

public class Administracion 
{
	private RemitoSRV remitoSRV;
	private List<String> remitosxml;
	private List<OrdenCompra> listadoCompras;
	private Vector<String> proveedores;
	private PlanProduccion planProduccion;
	private ArrayList<SolicitudReposicion> solicitudReposicion;
	private ArrayList<Producto> productos;
	private Deposito depositoCentral;
	private ProductoSRV productoSRV;
	private ProductosAComprarSRV productosAComprarSRV;
	private OrdenCompraSRV ordenCompraSRV;
	
	private static Administracion instancia;
	
	private Administracion()
	{
		remitoSRV= new RemitoSRV();
		remitosxml= new ArrayList<>();
		listadoCompras = new ArrayList<>();
		proveedores = new Vector<String>();
		solicitudReposicion = new ArrayList<SolicitudReposicion>();
		productos = new ArrayList<Producto>();
		productosAComprarSRV= new ProductosAComprarSRV();
		ordenCompraSRV= new OrdenCompraSRV();
		productoSRV= new ProductoSRV();
		planProduccion = new PlanProduccion();
		depositoCentral = new Deposito();
	}
	
	public static Administracion getInstancia() 
	{
		if (instancia == null) 
		{
			instancia = new Administracion();
		}
		return instancia;
	}
	
	public List<OrdenCompra> getListadoCompras() {
		return listadoCompras;
	}
	public void setListadoCompras(List<OrdenCompra> listadoCompras) {
		this.listadoCompras = listadoCompras;
	}
	public Vector<String> getProveedores() {
		return proveedores;
	}
	public void setProveedores(Vector<String> proveedores) {
		this.proveedores = proveedores;
	}
	public PlanProduccion getPlanProduccion() {
		return planProduccion;
	}
	public void setPlanProduccion(PlanProduccion planProduccion) {
		this.planProduccion = planProduccion;
	}
	public ArrayList<SolicitudReposicion> getSolicitudReposicion() {
		return solicitudReposicion;
	}
	public void setSolicitudReposicion(
			ArrayList<SolicitudReposicion> solicitudReposicion) {
		this.solicitudReposicion = solicitudReposicion;
	}
	public ArrayList<Producto> getProductos() {
		return productos;
	}
	public void setProductos(ArrayList<Producto> productos) {
		this.productos = productos;
	}
	public Deposito getDepositoCentral() {
		return depositoCentral;
	}
	public void setDepositoCentral(Deposito depositoCentral) {
		this.depositoCentral = depositoCentral;
	}

	public static void setInstancia(Administracion instancia) {
		Administracion.instancia = instancia;
	}
	
	public void agregarProducto(ProductoVO productoVO) throws ProductoException
	{
		Producto producto = new Producto();
		producto.buildFromVO(productoVO);
		if(productos.contains(producto))
		{
			throw new ProductoException("El producto ya existe.");
		}
		else
		{
			try 
			{
				productoSRV.agregarProducto(producto);
				productos.add(producto);
			} 
			catch (Exception e) 
			{
				throw new ProductoException("Error al grabar el producto.");
			}			
		}
	}

	public void bajaProd(String idprod) throws ProductoException
	{
		Producto producto = buscarProducto(idprod);
		if(productos.contains(producto))
		{
			try 
			{
				productoSRV.bajaProducto(producto);
				productos.remove(producto);
			} 
			catch (Exception e) 
			{
				throw new ProductoException("Error al grabar el producto.");
			}			
		}
		else
		{
			throw new ProductoException("El producto no existe.");
		}
	}
	
	public void modifProd(ProductoVO prod) throws ProductoException
	{
		Producto producto = new Producto();
		producto.buildFromVO(prod);
		try 
		{
			productoSRV.modificarProducto(producto);
			for (int i = 0 ; i < productos.size() ; i++)
			{
				if (productos.get(i).getId_producto() == producto.getId_producto())
				{
					productos.remove(i);
					break;
				}
			}
			productos.add(producto);
		} 
		catch (Exception e) 
		{
			throw new ProductoException("Error al grabar el producto.");
		}			
	}

	public Producto buscarProducto(String idprod)
	{
		Producto producto = productoSRV.getProducto(Integer.parseInt(idprod));
		return producto;
	}

	public ProductoVO buscarProductoVO(String idprod)
	{
		Producto producto = productoSRV.getProducto(Integer.parseInt(idprod));
		return producto.getVO();
	}

	public List<ProductoVO> getProductosVO() 
	{
		productos = productoSRV.getProductos();
		ArrayList<ProductoVO> prodVO = new ArrayList<ProductoVO>();
		for(int i = 0 ; i < productos.size() ; i++)
		{
			prodVO.add(productos.get(i).getVO());
		}
		return prodVO;
	}
	
	public ProductoVO getProducto(String nombre)
	{
		//Local
		for(int i = 0 ; i < productos.size() ; i++)
		{
			if (productos.get(i).getNombre().equals(nombre))
			{
				return productos.get(i).getVO();
			}
		}
		
		//BD
		ArrayList<Producto> prods = productoSRV.getProductos();
		for(int i = 0 ; i < prods.size() ; i++)
		{
			if (prods.get(i).getNombre().equals(nombre))
			{
				return prods.get(i).getVO();
			}
		}
		return null;
	}
	
	
	
	
	/*COMPRAR INSUMOS*/
	
	public void comprarInsumos() throws ParserConfigurationException, SAXException, IOException{
		
		
		class Auxiliar{
			float desc;
			float precioOrg;
			float monto;
			String proveedor;
		}
		
		
		List<ProductosAComprar>productos = this.productosAComprarSRV.getProductosAComprar();
		float subtotal=0;
		float precio,porcen,cant;
		
		for(ProductosAComprar p: productos){
			
		
		List<Float>lista=this.getValoresProveedorA(p.getProducto().getNombre());
		precio=lista.get(0);
		porcen=lista.get(1);
		cant=lista.get(2);
		
		subtotal=precio*p.getCantidad();
		if(p.getCantidad()>cant)
			subtotal=subtotal-(subtotal*(porcen/100));
		
		
		Auxiliar aux = new Auxiliar();
		aux.precioOrg=precio;
		aux.monto=subtotal;
		aux.proveedor="proveedorA";
		aux.desc=porcen;
		
		lista=this.getValoresProveedorB(p.getProducto().getNombre());
		
		precio=lista.get(0);
		porcen=lista.get(1);
		cant=lista.get(2);
		
		subtotal=precio*p.getCantidad();
		if(p.getCantidad()>cant)
			subtotal=subtotal-(subtotal*(porcen/100));
		
		
		
		if(subtotal<aux.monto){
			aux.precioOrg=precio;
			aux.monto=subtotal;
			aux.proveedor="proveedorB";
			aux.desc=porcen;
		}
		
		
		lista=this.getValoresProveedorC(p.getProducto().getNombre());
		
		precio=lista.get(0);
		porcen=lista.get(1);
		cant=lista.get(2);
		
		subtotal=precio*p.getCantidad();
		if(p.getCantidad()>cant)
			subtotal=subtotal-(subtotal*(porcen/100));
		
		
		if(subtotal<aux.monto){
			aux.precioOrg=precio;
			aux.monto=subtotal;
			aux.proveedor="proveedorC";
			aux.desc=porcen;
		}
		
		
		
		ActualizarProductosAComprar(aux.monto,aux.proveedor,p,aux.precioOrg, aux.desc);
		
		
		
		}
	}
	
			/*GENERDAR ORDEN DE COMPRA*/
	//no solamente genera la orden de compra sino que tambien arma el remito
	//hay tres tipos de remito hardcodeadps remito con exceso de mercaderia
	//remito con falta de mercaderia
	// remito con la cantidad correcta de mercaderia.
	
	public void generarOrdenesDeCompra() throws ParserConfigurationException, TransformerException{
		
		Random r=new Random();
		String docxml;
		XmlBuildOrdenCompra xml = XmlBuildOrdenCompra.getinstancia();
		XmlBuildRemito remito = XmlBuildRemito.getinstancia();
		float monto=0;
		
		for(OrdenCompra o: this.listadoCompras){
			for(Item_Compra i : o.getItemsCompra())
				monto=monto+i.getPrecio();
			o.setFecha(new Date());
			o.setTotal(monto);
			o.setNumeroOrden(r.nextInt(1000));
			/*GENERAR UN NUMERO DE ORDEN MENOS PICAPIEDRA
			 * */
			docxml =xml.createXmlOrden(o);
			o.setXml(docxml);
			
			
			this.ordenCompraSRV.PersistOrdenCompra(o);
			remitosxml.add(remito.crearRemitoCorrecto(o));
			
		}
	}
	
	/************FIN DEL METODO GENERAR ORDEN DE COMPRA
	 * @throws IOException 
	 * @throws SAXException 
	 * @throws ParserConfigurationException *******************/
	
	
	
	public void procesarRemitos() throws ParserConfigurationException, SAXException, IOException{
		
			
		Remito remito = new Remito();		
		SystemParserLeerRemito sys = SystemParserLeerRemito.getInstance();
		List<ItemRemito>lista = new ArrayList<>();
		List<ItemRemito> listaPersist = new ArrayList<>();
		
		for(String path : this.remitosxml){
			
			lista =sys.listaItemsRemito(path); 
			
			for(ItemRemito item : lista){
				int id=productoSRV.actualizarProducto(item.getProducto().getNombre());
				Producto p=productoSRV.getProducto(id);
				ItemRemito itemPersist = new ItemRemito();
				itemPersist.setCantidad(item.getCantidad());
				itemPersist.setProducto(p);
				listaPersist.add(itemPersist);
				
				
			}
			
			remito.setItems((ArrayList<ItemRemito>) listaPersist);
			OrdenCompra orden = new OrdenCompra();
			orden.setNumeroOrden(sys.getNumeroOrden(path));
			remito.setOrdenCompra(orden);
			remitoSRV.PersistRemito(remito);
			}
		}
	
	
	
	
	
	public void ControlarRemito(){
		
		remitoSRV.controlarRemito();
	}
		
		
		
		
	
	
	

	private void ActualizarProductosAComprar(float monto, String proveedor,ProductosAComprar p,float precioOrg,float desc) {
		
		int i;
		if(this.listadoCompras.size()==0){
		
			
			List<Item_Compra>items=new ArrayList<>();
			Item_Compra item = new Item_Compra();
			item.setCantidad(p.getCantidad());
			item.setDescuentoOtorgado(desc);
			item.setProducto(p.getProducto());
			item.setPrecio(monto);
			items.add(item);
			
			
			OrdenCompra orden = new OrdenCompra();
			orden.setProveedor(proveedor);
			orden.setItemsCompra(items);
			this.listadoCompras.add(orden);
			return;
		}
			
			
		
	
		for( i=0;i<this.listadoCompras.size() && !this.listadoCompras.get(i).getProveedor().equalsIgnoreCase(proveedor);i++){
				;
			}	
		if(i<this.listadoCompras.size()){
			Item_Compra item2 = new Item_Compra();
			item2.setCantidad(p.getCantidad());
			item2.setDescuentoOtorgado(desc);
			item2.setProducto(p.getProducto());
			item2.setPrecio(monto);
			this.listadoCompras.get(i).getItemsCompra().add(item2);
			
		}
		
		else{
			List<Item_Compra>items2=new ArrayList<>();
			Item_Compra item2 = new Item_Compra();
			item2.setCantidad(p.getCantidad());
			item2.setDescuentoOtorgado(desc);
			item2.setProducto(p.getProducto());
			item2.setPrecio(monto);
			items2.add(item2);
			
			
			OrdenCompra orden2 = new OrdenCompra();
			orden2.setProveedor(proveedor);
			orden2.setItemsCompra(items2);
			this.listadoCompras.add(orden2);
			
		}
		
		
	}
	
	/*METODOS PARA LEER DATOS  DE LOS XML*/

	private List<Float>getValoresProveedorA(String nombre) throws ParserConfigurationException, SAXException, IOException{
		SystemParserBuscador sys = SystemParserBuscador.getInstance();
		return sys.parseXml("xmls/proveedorA.xml", nombre);
	}


	private List<Float>getValoresProveedorB(String nombre) throws ParserConfigurationException, SAXException, IOException{
		SystemParserBuscador sys = SystemParserBuscador.getInstance();
		return sys.parseXml("xmls/proveedorB.xml", nombre);
	}
	
	
	private List<Float>getValoresProveedorC(String nombre) throws ParserConfigurationException, SAXException, IOException{
		SystemParserBuscador sys = SystemParserBuscador.getInstance();
		return sys.parseXml("xmls/proveedorC.xml", nombre);
	}
}